#![allow(non_camel_case_types, clippy::identity_op)]

/** Minimal xkb_common ffi wrapper, based on sctk's. */
use std::ffi::c_char;

#[repr(C)]
pub struct xkb_context {
    _private: [u8; 0],
}
#[repr(C)]
pub struct xkb_keymap {
    _private: [u8; 0],
}
#[repr(C)]
pub struct xkb_state {
    _private: [u8; 0],
}

pub type xkb_keycode_t = u32;
pub type xkb_keysym_t = u32;
pub type xkb_layout_index_t = u32;
pub type xkb_mod_mask_t = u32;

#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum xkb_context_flags {
    /** Do not apply any context flags. */
    XKB_CONTEXT_NO_FLAGS = 0,
}

#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum xkb_keymap_compile_flags {
    /** Do not apply any flags. */
    XKB_KEYMAP_COMPILE_NO_FLAGS = 0,
}

#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum xkb_keymap_format {
    /** The current/classic XKB text format, as generated by xkbcomp -xkb. */
    XKB_KEYMAP_FORMAT_TEXT_V1 = 1,
}

pub type xkb_state_component = u32;

external_library!(XkbCommon, "xkbcommon",
functions:
    fn xkb_keysym_to_utf32(xkb_keysym_t) -> u32,
    fn xkb_context_new(xkb_context_flags) -> *mut xkb_context,
    fn xkb_context_unref(*mut xkb_context) -> (),
    fn xkb_keymap_new_from_string(*mut xkb_context,
                                  *const c_char,
                                  xkb_keymap_format,
                                  xkb_keymap_compile_flags
                                 ) -> *mut xkb_keymap,
    fn xkb_keymap_unref(*mut xkb_keymap) -> (),
    fn xkb_state_key_get_one_sym(*mut xkb_state, xkb_keycode_t) -> xkb_keysym_t,
    fn xkb_state_new(*mut xkb_keymap) -> *mut xkb_state,
    fn xkb_state_unref(*mut xkb_state) -> (),
    fn xkb_state_update_mask(*mut xkb_state,
                             xkb_mod_mask_t,
                             xkb_mod_mask_t,
                             xkb_mod_mask_t,
                             xkb_layout_index_t,
                             xkb_layout_index_t,
                             xkb_layout_index_t
                            ) -> xkb_state_component,
);

#[cfg(feature = "dlopen")]
lazy_static::lazy_static!(
    pub static ref XKBCOMMON_OPTION: Option<XkbCommon> = unsafe {
        XkbCommon::open("libxkbcommon.so.0")
            .or_else(|_| XkbCommon::open("libxkbcommon.so"))
            .ok()
    };
    pub static ref XKBCOMMON_HANDLE: &'static XkbCommon = {
        XKBCOMMON_OPTION.as_ref().expect("Library libxkbcommon.so could not be loaded.")
    };
);
